package com.dingreading.cloud.mall.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.dingreading.cloud.common.base.R;
import com.dingreading.cloud.common.dto.LoginDataDto;
import com.dingreading.cloud.common.util.*;
import com.dingreading.cloud.common.util.qyweixin.AccessTokenDto;
import com.dingreading.cloud.common.util.qyweixin.QyWeiXinUtil;
import com.dingreading.cloud.common.util.qyweixin.QyWeixinMsg;
import com.dingreading.cloud.mall.dto.FormDto;
import com.dingreading.cloud.mall.dto.OrderFormDto;
import com.dingreading.cloud.mall.dto.StockOutDeliveryDto;
import com.dingreading.cloud.mall.entity.*;
import com.dingreading.cloud.mall.entity.table.OrderFormTableDef;
import com.dingreading.cloud.mall.mapper.OrderFormMapper;
import com.dingreading.cloud.mall.service.*;
import com.dingreading.cloud.mall.util.LoginInfoUtil;
import com.dingreading.cloud.mall.util.OrderFormV3Util;
import com.dingreading.cloud.mall.util.PurchaseUtil;
import com.dingreading.cloud.mall.util.ShopCartUtilV2;
import com.dingreading.cloud.mall.util.redis.RedisService;
import com.google.common.collect.Lists;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryCondition;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.update.UpdateChain;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@RefreshScope
@Service
public class OrderFormServiceImplV5 extends BaseServiceImpl<OrderFormMapper, OrderForm, OrderFormTableDef> implements OrderFormServiceV5 {

    @Override
    protected OrderFormTableDef getTable() {
        return OrderFormTableDef.orderForm;
    }

    @Value("${serverUrl}")
    private String serverUrl;
    @Value("${qyweixin.corpid}")
    private String corpid;
    @Value("${qyweixin.secret}")
    private String secret;
    @Value("${qyweixin.agentid}")
    private String agentid;
    @Value("${qyweixin.mallchatid}")
    private String mallchatid;
    @Value("${qyweixin.thirdUserid}")
    private String thirdUserid;
    @Value("${qyweixin.financechatid}")
    private String financechatid;


    @Resource
    protected OrderFormLogService orderFormLogService;
    @Resource
    protected OrderFormImageService orderFormImageService;
    @Resource
    protected WhStockOutService stockOutService;
    @Resource
    protected ShopCartV5Service shopCartV5Service;
    @Resource
    protected GoodsService goodsService;
    @Resource
    protected GoodsTypeService goodsTypeService;
    @Resource
    protected DeliveryAddressService deliveryAddressService;
    @Resource
    protected WhStockOutDeliveryService stockOutDeliveryService;
    @Resource
    protected StoresService storesService;
    @Resource
    protected GoodsTypeComboService goodsTypeComboService;
    @Resource
    protected WhStockOutDeliveryImgService stockOutDeliveryImgService;
    @Resource
    protected StoreGoodsDiscountService storeGoodsDiscountService;
    @Resource
    private OrderFormMapper orderFormMapper;
    @Resource
    private RedisService redisService;

    @Override
    public R<Object> pageList(
            PageUtil pageUtil, String storeUid, String staffUid, String keyword, Integer status
    ) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.storeUid.eq(storeUid))
                .and(table.staffUid.eq(staffUid));
        if (StringUtils.isNotBlank(keyword))
            condition.and(table.name.like(keyword)
                    .or(table.code.like(keyword))
                    .or(table.phone.like(keyword))
                    .or(table.storeName.like(keyword))
            );
        if (status != null)
            condition.and(table.status.eq(status));

        QueryWrapper wrapper = QueryWrapper.create()
                .select(table.allColumns)
                .from(table)
                .where(condition)
                .orderBy(table.id.desc());

        Page<OrderFormDto> page = getMapper().paginateAs(Page.of(pageUtil.getPage(), pageUtil.getRows()), wrapper, OrderFormDto.class);
        List<OrderFormDto> list = page.getRecords();
        if (CollectionUtils.isNotEmpty(list)) {
            List<String> codes = list.stream().map(OrderFormDto::getCode).collect(Collectors.toList());
            // 按订单编号获取购物车记录去除组合子商品记录
            List<ShopCart> shopCarts = shopCartV5Service.mainListByCodeIn(codes);
            Map<String, List<ShopCart>> map = new HashMap<>();
            if (CollectionUtils.isNotEmpty(shopCarts))
                map = shopCarts.stream().collect(Collectors.groupingBy(ShopCart::getCode));

            for (OrderFormDto form : list) {
                form.setShopCartList(map.get(form.getCode()));
            }
        }

        Map<String, String> statusNumMap = new HashMap<>();
        statusNumMap.put("ok", "0");
        statusNumMap.put("confirm", "0");
        statusNumMap.put("pay", "0");
        statusNumMap.put("cancel", "0");
        statusNumMap.put("send", "0");

        List<JSONObject> stautsNumList = orderFormMapper.getStatusNum(storeUid, staffUid);
        if (CollectionUtils.isNotEmpty(stautsNumList)) {
            for (JSONObject jsonObject : stautsNumList) {
                String num = jsonObject.getString("num");
                String objStatus = jsonObject.getString("status");
                String statusName = jsonObject.getString("statusName");
                statusNumMap.put(statusName, num);
            }
        }

        PageDataDto data = new PageDataDto();
        data.setTotal(page.getTotalRow());
        data.setList(list);
        data.setData(statusNumMap);
        return R.ok(data);
    }

    @Override
    public R<Object> get(String storeUid, String staffUid, String code) {
        Stores stores = storesService.getByUid(storeUid);
        if (null == stores)
            return R.fail("门店信息获取失败");

        OrderForm form = getByCode(staffUid, code);
        if (form == null)
            return R.fail("订单获取失败");

        // 购物车商品记录
        List<ShopCart> carts = shopCartV5Service.mainListByStaffUidAndCode(staffUid, code);

        // 查看银行转账截图
        List<OrderFormImage> imageList = orderFormImageService.getByOrderCode(code);

        // 获取快递信息
        JSONArray express = new JSONArray();
        if (StringUtils.isNotBlank(form.getExpressCode())) {
            // 旧版订单快递信息
            List<String> strings = Arrays.stream(StringUtils.split(form.getExpressCode(), ";")).collect(Collectors.toList());
            for (String string : strings) {
                if (StringUtils.isNotBlank(string)) {
                    String[] split = StringUtils.split(string, "*");
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put("expressCode", split[0]);
                    jsonObject.put("expressName", split[1]);
                    jsonObject.put("expressPrice", null);
                    jsonObject.put("expressTime", null);
                    jsonObject.put("packageNum", null);
                    jsonObject.put("goodsList", new JSONArray());
                    express.add(jsonObject);
                }
            }
        }

        // 获取发货完成的出库单
        List<WhStockOut> outList = stockOutService.getByOrderCodeV2(code);
        if (CollectionUtils.isNotEmpty(outList)) {
            List<String> outCodes = outList.stream().map(WhStockOut::getOutCode).collect(Collectors.toList());
            List<WhStockOutDelivery> deliveryList = stockOutDeliveryService.listByOutCodes(outCodes);
            if (CollectionUtils.isNotEmpty(deliveryList)) {
                List<Long> deliveryIdList = deliveryList.stream().map(WhStockOutDelivery::getId).collect(Collectors.toList());
                List<WhStockOutDeliveryImg> deliveryImgList = stockOutDeliveryImgService.listByDeliveryIdIn(deliveryIdList);
                Map<Long, List<WhStockOutDeliveryImg>> imgMap = new HashMap<>();
                if (CollectionUtils.isNotEmpty(deliveryImgList)) {
                    imgMap = deliveryImgList.stream().collect(Collectors.groupingBy(WhStockOutDeliveryImg::getDeliveryId));
                }

                for (WhStockOutDelivery delivery : deliveryList) {
                    StockOutDeliveryDto deliveryObj = PurchaseUtil.getDeliveryObj(delivery, imgMap.get(delivery.getId()));
                    express.add(deliveryObj);
                }
            }
        }

        List<OrderFormLog> logs = null;
        if (AccountUtil.isSelfStore(stores.getOperationType())) {
            // 自营门店获取订单操作日志
            logs = orderFormLogService.getByCode(code);
        }

        FormDto dto = new FormDto();
        dto.setOrderForm(form);
        dto.setShopCartList(carts);
        dto.setExpressArr(express);
        dto.setImageList(imageList);
        dto.setLogList(logs);
        return R.ok(dto);
    }

    @Override
    public R<Object> getFormStatus(String staffUid, String code) {
        QueryCondition condition = QueryCondition.createEmpty();
        if (staffUid != null)
            condition.and(table.staffUid.eq(staffUid));
        condition.and(table.code.eq(code));

        QueryWrapper wrapper = QueryWrapper.create()
                .select(table.status)
                .where(condition);
        Integer i = getMapper().selectObjectByQueryAs(wrapper, Integer.class);
        return R.ok(i);
    }

    @Override
    public void updatePayChannelCodeAndCorpPay(String staffUid, String code, String payChannelCode) {
        QueryCondition condition = QueryCondition.createEmpty();
        if (staffUid != null)
            condition.and(table.staffUid.eq(staffUid));
        condition.and(table.code.eq(code));

        UpdateChain.of(OrderForm.class)
                .set(table.payChannelCode, payChannelCode)
                .where(condition)
                .update();
    }

    @Override
    public void updatePayChannelCode(String staffUid, String code, String payChannelCode) {
        QueryCondition condition = QueryCondition.createEmpty();
        if (staffUid != null)
            condition.and(table.staffUid.eq(staffUid));
        condition.and(table.code.eq(code));

        UpdateChain.of(OrderForm.class)
                .set(table.payChannelCode, payChannelCode)
                .where(condition)
                .update();
    }

    @Override
    public boolean payOkGoodsOrder(String staffUid, String code, Integer payType, String tradeType, String buyerId, String tradeNo, Integer payOnline, String payTime) {
        QueryCondition condition = QueryCondition.createEmpty();
        if (staffUid != null)
            condition.and(table.staffUid.eq(staffUid));
        condition.and(table.code.eq(code));
        condition.and(table.status.in(EnumType.OrderForm.WAIT_CONFIRM.getType(), EnumType.OrderForm.WAIT_PAY.getType())
                .or(table.payChannelCode.eq(EnumType.PayChannelCode.BANK.getType()).and(table.status.eq(EnumType.OrderForm.APPLY_BANKPAY.getType())))
        );

        int waitSendType = EnumType.OrderForm.WAIT_SEND.getType();
        String waitSendName = EnumType.OrderForm.WAIT_SEND.getName();

        UpdateChain<OrderForm> update = UpdateChain.of(OrderForm.class);
        update.set(table.payType, payType)
                .set(table.tradeType, tradeType)
                .set(table.payTime, payTime)
                .set(table.buyerId, buyerId)
                .set(table.tradeNo, tradeNo)
                .set(table.status, waitSendType)
                .set(table.statusName, waitSendName);
        if (payOnline.equals(1)) {
            // 线上付款，财务审核状态默认系统审核通过
            update.set(table.financeStatus, EnumType.OrderForm.SYSTEM_CHECK_OK.getType())
                    .set(table.financeStatusName, EnumType.OrderForm.SYSTEM_CHECK_OK.getName());
        }
        return update.where(condition).update();
    }

    @Override
    public boolean payOkGiftGoodsOrder(String staffUid, String code, Integer payType, String tradeType, String payChannelCode, String payTime) {
        QueryCondition condition = QueryCondition.createEmpty();
        if (staffUid != null)
            condition.and(table.staffUid.eq(staffUid));
        condition.and(table.code.eq(code));
        condition.and(table.status.in(EnumType.OrderForm.WAIT_CONFIRM.getType(), EnumType.OrderForm.WAIT_PAY.getType()));

        int waitSendType = EnumType.OrderForm.WAIT_SEND.getType();
        String waitSendName = EnumType.OrderForm.WAIT_SEND.getName();

        UpdateChain<OrderForm> update = UpdateChain.of(OrderForm.class);
        update.set(table.payType, payType)
                .set(table.tradeType, tradeType)
                .set(table.payChannelCode, payChannelCode)
                .set(table.payTime, payTime)
                .set(table.status, waitSendType)
                .set(table.statusName, waitSendName)
                // 线上付款，财务审核状态默认系统审核通过
                .set(table.financeStatus, EnumType.OrderForm.SYSTEM_CHECK_OK.getType())
                .set(table.financeStatusName, EnumType.OrderForm.SYSTEM_CHECK_OK.getName());
        return update.where(condition).update();
    }


    @Override
    public R<Object> judgeCancel(String storeUid, String staffUid, String code) {
        OrderForm form = getByCode(staffUid, code);
        if (null == form)
            return R.fail("订单获取失败");

        Integer status = form.getStatus();

        ArrayList<Integer> statusList = Lists.newArrayList(EnumType.OrderForm.WAIT_CONFIRM.getType(), EnumType.OrderForm.WAIT_PAY.getType());
        if (!statusList.contains(status))
            return R.fail("订单状态不符合订单状态：" + EnumType.OrderForm.getStatus(status));
        return R.ok();
    }

    @Override
    public OrderForm getByCode(String staffUid, String code) {
        QueryCondition condition = QueryCondition.createEmpty();
        if (staffUid != null)
            condition.and(table.staffUid.eq(staffUid));
        condition.and(table.code.eq(code));
        return getMapper().selectOneByCondition(condition);
    }

    @Override
    public R<Object> cancel(String storeUid, String staffUid, String staffName, String code, String remark) {
        OrderForm form = getByCode(staffUid, code);
        if (form == null)
            return R.fail("订单获取失败");

        Integer status = form.getStatus();

        ArrayList<Integer> statusList = Lists.newArrayList(EnumType.OrderForm.WAIT_CONFIRM.getType(), EnumType.OrderForm.WAIT_PAY.getType());
        if (!statusList.contains(status))
            return R.fail("订单状态不符合订单状态：" + EnumType.OrderForm.getStatus(status));

        QueryCondition condition = QueryCondition.createEmpty();
        if (staffUid != null)
            condition.and(table.staffUid.eq(staffUid));
        condition.and(table.code.eq(code))
                .and(table.status.in(EnumType.OrderForm.WAIT_CONFIRM.getType(), EnumType.OrderForm.WAIT_PAY.getType()));
        boolean l = UpdateChain.of(OrderForm.class)
                .set(table.status, EnumType.OrderForm.CANCEL.getType())
                .set(table.statusName, EnumType.OrderForm.CANCEL.getName())
                .where(condition)
                .update();
        if (!l)
            return R.fail("修改失败订单状态：" + EnumType.OrderForm.getStatus(form.getStatus()));

        // 取消购物车记录
        shopCartV5Service.cancelShopCarts(staffUid, code);

        // 添加订单操作记录
        OrderFormLog log = OrderFormV3Util.newStaffLog(form.getCode(), staffUid, staffName,
                EnumType.OrderForm.CANCEL.getType(), "取消订单", remark);
        orderFormLogService.saveOrUpdate(log);

        // 删除redis过期自动取消的商城订单号
        OrderFormV3Util.deleteMallCodeFromRedisExpire(code);
        return R.ok();
    }

    @Override
    public R<Object> editAddress(String storeUid, String staffUid, String code, Long deliveryId) {
        OrderForm form = getByCode(staffUid, code);
        if (form == null)
            return R.fail("订单获取失败");

        DeliveryAddress address = deliveryAddressService.getById(deliveryId);
        if (address == null)
            return R.fail("收货地址获取失败");

        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.staffUid.eq(staffUid))
                .and(table.code.eq(code))
                .and(table.status.in(EnumType.OrderForm.WAIT_CONFIRM.getType(), EnumType.OrderForm.WAIT_PAY.getType(), EnumType.OrderForm.APPLY_BANKPAY.getType()));

        boolean l = UpdateChain.of(OrderForm.class)
                .set(table.deliveryId, address.getId())
                .set(table.name, address.getName())
                .set(table.phone, address.getPhone())
                .set(table.address, address.getProvinces() + address.getAddress())
                .where(condition)
                .update();
        if (!l)
            return R.fail("修改失败订单状态：" + EnumType.OrderForm.getStatus(form.getStatus()));

        return R.ok();
    }

    @Override
    public R<Object> deleteForm(String storeUid, String staffUid, String code) {
        OrderForm form = getByCode(staffUid, code);
        if (form == null)
            return R.fail("订单获取失败");

        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.staffUid.eq(staffUid))
                .and(table.code.eq(code))
                .and(table.status.notIn(EnumType.OrderForm.OK.getType(),
                        EnumType.OrderForm.WAIT_SEND.getType(),
                        EnumType.OrderForm.SENDING.getType(),
                        EnumType.OrderForm.REFUND.getType()));
        long l = getMapper().deleteByCondition(condition);
        if (l <= 0)
            return R.fail("删除失败订单状态：" + EnumType.OrderForm.getStatus(form.getStatus()));

        QueryCondition deleteCondition = QueryCondition.createEmpty();
        if (staffUid != null)
            deleteCondition.and(table.staffUid.eq(staffUid));
        deleteCondition.and(table.code.eq(code))
                .and(table.status.notIn(EnumType.ShopCart.PAYED.getType(), EnumType.ShopCart.SEND.getType(), EnumType.ShopCart.REFUND.getType()));
        getMapper().deleteByCondition(deleteCondition);
        return R.ok();
    }

    @Override
    public R<Object> againAddShopCart(String storeUid, String staffUid, String staffName, String code) {
        Stores stores = storesService.getByUid(storeUid);
        if (null == stores)
            return R.fail("门店信息获取失败");
        String storesCorpUid = stores.getCorpUid();

        // 轻量门店的商品折扣规则
        StoreGoodsDiscount storeGoodsDiscount = storeGoodsDiscountService.getEnabledDiscount(storeUid);
        Double storeGoodsDiscountRate = null;
        if (storeGoodsDiscount != null) {
            storeGoodsDiscountRate = storeGoodsDiscount.getDiscountRate();
        }

        OrderForm form = getByCode(staffUid, code);
        if (null == form)
            return R.fail("订单获取失败");
        if (!form.getStatus().equals(EnumType.OrderForm.CANCEL.getType()))
            return R.fail("不是取消的订单不能操作");

        List<ShopCart> mainAndChildCartList = shopCartV5Service.mainListAndChildListByCode(code);
        if (CollectionUtils.isEmpty(mainAndChildCartList))
            return R.fail("订单的购物车信息不存在");

        Set<Long> goodsIds = new HashSet<>();
        Set<Long> goodsTypeIds = new HashSet<>();
        Set<Long> mainGoodsTypeIds = new HashSet<>();
        List<ShopCart> mainCartList = new ArrayList<>();

        for (ShopCart cart : mainAndChildCartList) {
            // 商品id集合
            goodsIds.add(cart.getGoodsId());
            goodsTypeIds.add(cart.getGoodsTypeId());

            // 组合商品的商品配置
            if (cart.getComboType().equals(1))
                mainGoodsTypeIds.add(cart.getMainGoodsTypeId());

            // 父购物车商品
            if (cart.getMainComboType().equals(0) || (cart.getComboType().equals(1) && cart.getMainComboType().equals(1)))
                mainCartList.add(cart);
        }

        // 组合商品的商品配置
        Map<Long, List<GoodsTypeCombo>> goodsTypeComboMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(mainGoodsTypeIds)) {
            List<GoodsTypeCombo> goodsTypeComboList = goodsTypeComboService.listByMainGoodsTypeIds(new ArrayList<>(mainGoodsTypeIds));
            if (CollectionUtils.isEmpty(goodsTypeComboList))
                return R.fail("组合商品的商品配置获取失败");
            goodsTypeComboMap = goodsTypeComboList.stream().collect(Collectors.groupingBy(GoodsTypeCombo::getMainGoodsTypeId));
        }

        // 获取商品和商品规格信息
        List<Long> goodsIdList = new ArrayList<>(goodsIds);
        List<Long> goodsTypeIdList = new ArrayList<>(goodsTypeIds);

        List<Goods> goodsList = goodsService.listByIds(goodsIdList);
        if (CollectionUtils.isEmpty(goodsList) || goodsIdList.size() != goodsList.size())
            return R.fail("组合商品内的商品获取失败");
        List<GoodsType> goodsTypeList = goodsTypeService.listByIds(goodsTypeIdList);
        if (CollectionUtils.isEmpty(goodsTypeList) || goodsTypeIdList.size() != goodsTypeList.size())
            return R.fail("组合商品内的商品规格获取失败");

        Map<Long, Goods> goodsMap = goodsList.stream().collect(Collectors.toMap(Goods::getId, Function.identity()));
        Map<Long, GoodsType> goodsTypeMap = goodsTypeList.stream().collect(Collectors.toMap(GoodsType::getId, Function.identity()));

        for (GoodsType goodsType : goodsTypeList) {
            if (goodsType.getEnabled().equals(0)) {
                Goods childGoods = goodsMap.get(goodsType.getGoodsId());
                return R.fail("商品规格已下架" + childGoods.getName() + "/" + goodsType.getName());
            }
        }

        List<ShopCart> newCartList = new ArrayList<>();
        for (ShopCart cart : mainCartList) {
            Goods goods = goodsMap.get(cart.getGoodsId());
            GoodsType goodsType = goodsTypeMap.get(cart.getGoodsTypeId());
            if (goods == null || goodsType == null)
                return R.fail("购物车的商品和商品规格获取失败");

            // 查询购物车内是否有该商品规格
            ShopCart data = shopCartV5Service.getByStaffIdAndGoodsIdAndTypeId(storeUid, staffUid, cart.getGoodsId(), cart.getGoodsTypeId(), cart.getMainComboType(), cart.getComboType());

            double totalWeight = 0;
            int paymentMethod = 1;
            String mainUid = data == null ? KitUtil.getUuid() : data.getUid();

            // 如果是组合商品，则修改子购物车记录的购买数量
            if (cart.getMainComboType().equals(1) && cart.getComboType().equals(1)) {
                List<GoodsTypeCombo> comboList = goodsTypeComboMap.get(cart.getGoodsTypeId());
                Map<Long, GoodsTypeCombo> comboMap = comboList.stream().collect(Collectors.toMap(GoodsTypeCombo::getGoodsTypeId, Function.identity()));

                List<ShopCart> childCartList = shopCartV5Service.childListByStoreUidAndStaffUidAndUid(storeUid, staffUid, mainUid);
                if (CollectionUtils.isEmpty(childCartList)) {
                    for (Map.Entry<Long, GoodsTypeCombo> entry : comboMap.entrySet()) {
                        GoodsTypeCombo goodsTypeCombo = entry.getValue();

                        Goods childGoods = goodsMap.get(goodsTypeCombo.getGoodsId());
                        GoodsType childGoodsType = goodsTypeMap.get(goodsTypeCombo.getGoodsTypeId());

                        // 包含有银行转账
                        if (paymentMethod == 1 && childGoods.getPaymentMethod().equals(2))
                            paymentMethod = 2;

                        int buyNum = cart.getBuyNum() * goodsTypeCombo.getNum();
                        ShopCart childCart = ShopCartUtilV2.newChildComboShopCart(
                                childGoods, childGoodsType, storesCorpUid, storeUid, staffUid,
                                EnumType.ShopCartType.ADD.getType(), cart.getMainComboType(), KitUtil.getUuid(), buyNum, staffUid, staffName,
                                mainUid, goods.getId(), goods.getName(), goodsType.getId(), goodsType.getName(),
                                null
                        );

                        totalWeight = DoubleUtil.sum(totalWeight, childCart.getTotalWeight());

                        newCartList.add(childCart);
                    }
                } else {
                    // 获取购物车里的组合商品内的商品购物车记录
                    for (ShopCart childCart : childCartList) {
                        GoodsTypeCombo goodsTypeCombo = comboMap.get(childCart.getGoodsTypeId());

                        Goods childGoods = goodsMap.get(childCart.getGoodsId());
                        GoodsType childGoodsType = goodsTypeMap.get(childCart.getGoodsTypeId());

                        // 包含有银行转账
                        if (paymentMethod == 1 && childGoods.getPaymentMethod().equals(2))
                            paymentMethod = 2;

                        int buyNum = cart.getBuyNum() * goodsTypeCombo.getNum() + childCart.getBuyNum();
                        // 修改组合商品规格的购物车记录
                        ShopCartUtilV2.mdyShopCart(
                                childCart, childGoods, childGoodsType, buyNum, staffUid, staffName, null
                        );

                        totalWeight = DoubleUtil.sum(totalWeight, childCart.getTotalWeight());
                        newCartList.add(childCart);
                    }
                }
            }

            if (data == null) {
                // 购物车内没有商品
                if (cart.getComboType().equals(0)) {
                    // 新增正常商品的购物车记录
                    data = ShopCartUtilV2.newShopCart(
                            goods, goodsType, storesCorpUid, storeUid, staffUid,
                            EnumType.ShopCartType.ADD.getType(), cart.getMainComboType(), mainUid, cart.getBuyNum(),
                            staffUid, staffName, null, storeGoodsDiscountRate
                    );
                } else {
                    // 新增组合商品的购物车记录
                    data = ShopCartUtilV2.newMainComboShopCart(
                            goods, goodsType, storesCorpUid, storeUid, staffUid,
                            EnumType.ShopCartType.ADD.getType(), cart.getMainComboType(), mainUid, cart.getBuyNum(),
                            staffUid, staffName, paymentMethod, totalWeight, null,
                            storeGoodsDiscountRate
                    );
                }
            } else {
                // 购物车内有商品
                int buyNum = cart.getBuyNum() + data.getBuyNum();
                // 修改组合商品规格的购物车记录
                if (cart.getComboType().equals(0))
                    ShopCartUtilV2.mdyShopCart(
                            data, goods, goodsType, buyNum, staffUid, staffName, storeGoodsDiscountRate
                    );
                else
                    ShopCartUtilV2.mdyMainComboShopCart(
                            data, goods, goodsType, buyNum, paymentMethod, totalWeight, staffUid, staffName,
                            storeGoodsDiscountRate
                    );
            }
            newCartList.add(data);
        }

        // 验证购物车商品能否重新加入购物车
        String resultMsg = OrderFormV3Util.verifyAgainAddShopCarts(AccountUtil.isSelfStore(stores.getOperationType()), false,
                newCartList, goodsMap, goodsTypeMap, goodsTypeIdList);
        if (StringUtils.isNotBlank(resultMsg))
            return R.fail(resultMsg);

        shopCartV5Service.saveOrUpdateBatch(newCartList);
        return R.fail(0, "重新加入购物车成功");
    }

    @Override
    public R<Object> uploadBankPayImg(String storeUid, String staffUid, String staffName, String code, MultipartFile file) throws Exception {
        OrderForm form = getByCode(staffUid, code);
        if (null == form)
            return R.fail("订单获取失败");
        if (!form.getStatus().equals(EnumType.OrderForm.WAIT_PAY.getType()))
            return R.fail("订单状态不符合");

        long imgNum = orderFormImageService.getImgNum(code);
        if (imgNum >= 10)
            return R.fail("图片最多上传10张");

        // 上传图片到服务器
        R<String> r = LocalFileUtil.uploadImg(LocalFileUtil.orderFormBaseDir, file);
        if (R.isError(r))
            return R.fail(r.getMsg());

        String imageUrl = r.getData();
        OrderFormImage image = new OrderFormImage();
        image.setOrderCode(code);
        image.setStaffUid(staffUid);
        image.setImgUrl(imageUrl);
        orderFormImageService.saveOrUpdate(image);

        JSONObject object = new JSONObject();
        object.put("id", image.getId());
        object.put("imgUrl", imageUrl);
        return R.ok(object);
    }

    @Override
    public R<Object> dropBankPayImg(String storeUid, String staffUid, String code, Long imgId) {
        OrderForm form = getByCode(staffUid, code);
        if (form == null)
            return R.fail("订单获取失败");
        if (!form.getStatus().equals(EnumType.OrderForm.WAIT_PAY.getType()))
            return R.fail("订单状态不符合");

        OrderFormImage image = orderFormImageService.getById(imgId);
        if (null == image)
            return R.fail("图片不存在");

        long l = orderFormImageService.dropByOrderCodeAndId(code, imgId);
        if (l <= 0)
            return R.failDel();

        // 删除服务器上的截图
        if (StringUtils.isNotBlank(image.getImgUrl())) {
            LocalFileUtil.deleteImg(LocalFileUtil.orderFormBaseDir, image.getImgUrl());
        }
        return R.ok();
    }

    @Override
    public R<Object> getBankPayImg(String storeUid, String staffUid, String code) {
        OrderForm form = getByCode(staffUid, code);
        if (null == form)
            return R.fail("订单获取失败");
        if (!form.getStatus().equals(EnumType.OrderForm.WAIT_PAY.getType()))
            return R.fail("订单状态不符合");

        List<OrderFormImage> list = orderFormImageService.getByOrderCode(code);
        return R.ok(list);
    }

    @Override
    public R<Object> bankPay(HttpServletRequest request, String storeUid, String staffUid, String staffName, String code) {
        R<Object> r = LoginInfoUtil.getLoginDto(request);
        if (R.isError(r)) return r;
        LoginDataDto loginDto = (LoginDataDto) r.getData();

        OrderForm form = getByCode(staffUid, code);
        if (null == form)
            return R.fail("获取订单失败");
        if (!form.getStatus().equals(EnumType.OrderForm.WAIT_PAY.getType()))
            return R.fail("订单状态不符合");

        long imgNum = orderFormImageService.getImgNum(code);
        if (imgNum == 0)
            return R.fail("请先上传银行转账图片");
        if (imgNum > 10)
            return R.fail("银行转账图片最多上传10张");

        // 验证订单有效性
        String msg = OrderFormV3Util.verifyOrderForm(form, true, AccountUtil.isSelfStore(loginDto.getCurrentOperationType()));
        if (StringUtils.isNotBlank(msg))
            return R.fail(msg);

        // 订单更新支付渠道和支付时间
        String payTime = DateUtil.getNowDatetimeStr();

        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.storeUid.eq(storeUid))
                .and(table.code.eq(code))
                .and(table.status.eq(EnumType.OrderForm.WAIT_PAY.getType()));

        String channelCode = EnumType.PayChannelCode.BANK.getType();
        int applyBankpayType = EnumType.OrderForm.APPLY_BANKPAY.getType();
        String applyBankpayName = EnumType.OrderForm.APPLY_BANKPAY.getName();
        int financeCheckWaitType = EnumType.OrderForm.FINANCE_CHECK_WAIT.getType();
        String financeCheckWaitName = EnumType.OrderForm.FINANCE_CHECK_WAIT.getName();

        boolean l = UpdateChain.of(OrderForm.class)
                .set(table.payChannelCode, channelCode)
                .set(table.payTime, payTime)
                .set(table.status, applyBankpayType)
                .set(table.statusName, applyBankpayName)
                .set(table.financeStatus, financeCheckWaitType)
                .set(table.financeStatusName, financeCheckWaitName)
                .where(condition)
                .update();
        if (!l)
            return R.fail("申请银行转账失败");

        // 添加操作日志
        OrderFormLog log = OrderFormV3Util.newStaffLog(code, staffUid, staffName,
                EnumType.OrderForm.APPLY_BANKPAY.getType(), "上传图片，申请银行转账", "");
        orderFormLogService.saveOrUpdate(log);

        // 删除redis过期自动取消的商城订单号
        OrderFormV3Util.deleteMallCodeFromRedisExpire(code);

        // 企业微信获取access_token
        String accessToken = (String) redisService.get(RedisParam.QYWEINXIN_ACCESS_TOKEN);
        if (StringUtils.isBlank(accessToken)) {
            AccessTokenDto dto = QyWeiXinUtil.getAccessToken(corpid, secret);
            if (dto != null) {
                accessToken = dto.getAccess_token();
                int expires_in = dto.getExpires_in();
                // redis缓存accessToken
                redisService.set(RedisParam.QYWEINXIN_ACCESS_TOKEN, accessToken, expires_in);
            }
        }

        // 发送钉钉机器人群消息通知
        if (AccountUtil.isJointOperation(loginDto.getCurrentOperationType(), form.getStaffUid())) {
            // 采购下单或是联营下单
            String bankApplyMsg = QyWeixinMsg.jointOperationBankApplyMsg(serverUrl, form.getStoreName(), form.getCode());
            QyWeiXinUtil.sendToUser(accessToken, agentid, thirdUserid, bankApplyMsg);
        } else {
            String bankApplyMsg = QyWeixinMsg.bankApplyMsg(serverUrl, form.getStoreName(), form.getCode());
            QyWeiXinUtil.sendToChat(accessToken, mallchatid, bankApplyMsg);
        }
        // 发送钉钉机器人群消息通知
        QyWeiXinUtil.sendToChat(accessToken, financechatid, QyWeixinMsg.bankCheckMsg(serverUrl, form.getStoreName(), form.getCode()));
        return R.ok();
    }

    @Override
    public R<Object> cancelBankPay(String storeUid, String staffUid, String staffName, String code) {
        OrderForm form = getByCode(staffUid, code);
        if (form == null)
            return R.fail("订单获取失败");
        if (!form.getStatus().equals(EnumType.OrderForm.APPLY_BANKPAY.getType()))
            return R.fail("订单状态不符合");

        QueryCondition condition = QueryCondition.createEmpty();
        if (StringUtils.isNotBlank(storeUid))
            condition.and(table.storeUid.eq(storeUid));
        condition.and(table.code.eq(code))
                .and(table.status.eq(EnumType.OrderForm.APPLY_BANKPAY.getType()));

        int waitPayType = EnumType.OrderForm.WAIT_PAY.getType();
        String waitPayName = EnumType.OrderForm.WAIT_PAY.getName();

        boolean l = UpdateChain.of(OrderForm.class)
                .set(table.payChannelCode, "")
                .set(table.payTime, "")
                .set(table.status, waitPayType)
                .set(table.statusName, waitPayName)
                .where(condition)
                .update();
        if (!l)
            return R.fail("操作失败");
        // 取消购物记录
        shopCartV5Service.cancelShopCarts(null, code);

        // 删除图片记录
        long l1 = orderFormImageService.dropByOrderCode(code);
        if (l1 > 0) {
            // 删除图片文件
            List<OrderFormImage> imageList = orderFormImageService.getByOrderCode(code);
            if (CollectionUtils.isNotEmpty(imageList)) {
                List<String> urlList = imageList.stream().map(OrderFormImage::getImgUrl).collect(Collectors.toList());
                // 删除服务器上的截图
                LocalFileUtil.deleteImgList(LocalFileUtil.orderFormBaseDir, urlList);
            }
        }
        // 添加操作日志
        OrderFormLog log = OrderFormV3Util.newStaffLog(code, staffUid, staffName,
                EnumType.OrderForm.CANCEL_BANKPAY.getType(), "取消银行转账", "");
        orderFormLogService.saveOrUpdate(log);

        return R.ok();
    }

}
